/**
 * @file Quaternion.h
 * @author  Aljosa Osep <aljosa.osep@gmail.com, Fletcher Dunn, Ian Parnberry>
 * @version 1.0
 *
 * @section LICENSE
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:

 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.

 *  2. Redistributions in binary form must reproduce the above copyright notice, this list
 *     of conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.

 * THIS SOFTWARE IS PROVIDED BY <Aljosa Osep> ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <Aljosa Osep>> OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of <Aljosa Osep>.
 *
 * @section DESCRIPTION
 *
 * Quaternion - class representing an quaternion
 * Based on examples from 3D Math Premier of Graphics and Games Development book
 * Original authors: Fletcher Dunn, Ian Parnberry. Thanks!
 */

#ifndef QUATERNION_H
#define QUATERNION_H

// Includes
#include <cassert>



//using namespace xEngine::PlatformIndependent;

// Forward declarations
// class Vector3;
// class EulerAngles;

namespace xEngine
{
    namespace PlatformIndependent
    {
        namespace Math
        {
            class Vector3;
            class EulerAngles;

            /**
             * Quaternion class
             *
             * Implements quaternion for the purpose of representing an angular displacement (orientation) in 3D
             */
            class Quaternion {
                public:
                float w, x, y, z; // Quaternion values

                /// Operations
                void identity(); // Set to identity

                // Set quaternion to a specific rotation
                void setToRotateAboutX(float theta);
                void setToRotateAboutY(float theta);
                void setToRotateAboutZ(float theta);
                void setToRotateAboutAxis(const Vector3 &axis, float theta);

                // Setup to pefrom object <-> inertial rotations, in Euler format
                void setToRotateObjectToInertial(const EulerAngles &orientation);
                void setToRotateInertialToObject(const EulerAngles &orientation);

                // Cross product
                Quaternion operator *(const Quaternion &a) const;
                Quaternion &operator *=(const Quaternion &a);

                void normalize(); // Normalize the quaternion

                // Extract and return orientation angle & axis
                float getRotationAngle() const;
                Vector3 getRotationAxis() const;
            };

            /// Nonmembers
            extern float dotProduct(const Quaternion &a, const Quaternion &b); // Dot product
            extern Quaternion slerp(const Quaternion &q0, const Quaternion &q1, float t); // Spherical line interpolation
            extern Quaternion conjugate(const Quaternion &q); // Conjugate
            extern Quaternion pow(const Quaternion &q, float exponent);

        }
    }
}

#endif // QUATERNION_H
